import math
import os
import re
import time

import wsgiref.handlers

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template

import utils
import model

class Login(webapp.RequestHandler):
    '''
    '''
    def get(self):
        '''
        '''
        self.redirect('/')

class Logout(webapp.RequestHandler):
    '''
    '''
    def get(self):
        '''
        '''
        # empty the the attempts of th current user
        utils.clear_visit()

        # get the current user
        user = users.get_current_user()

        # logout the current user
        if user:
            self.redirect(users.create_logout_url('/login'))

class New(webapp.RequestHandler):
    '''
    '''
    def get(self):
        '''
        '''
        # set the template with empty values
        template_values = { 'title': 'New',
                            'password': None,
                            'key': None }

        # root path
        root = os.path.dirname(__file__)

        # find the template
        path = os.path.join(root, 'templates', 'edit.html')

        # generate the content
        content = template.render(path, template_values)

        # display the page
        self.response.out.write(content)

class Check(webapp.RequestHandler):
    '''
    '''
    def post(self):
        '''
        '''
        # get the password key
        key = self.request.get('key')

        # manage the action to trigger after check
        if self.request.get('view') != '':

            # set the template
            template_values = { 'title': 'Check',
                                'key': key }

            # root path
            root = os.path.dirname(__file__)

            # find the template
            path = os.path.join(root, 'templates', 'check.html')

            # generate the content
            content = template.render(path, template_values)

            # display the page
            self.response.out.write(content)

        # redirect to the edit page
        elif self.request.get('edit') != '':
            self.redirect('/edit?key=%s' % key)

        # redirect to the delete action
        elif self.request.get('delete') != '':
            # get the encrypted password from the db
            password = model.Password().get(key)

            # set the template
            template_values = { 'title': 'Delete',
                                'password': password,
                                'key': key }

            # root path
            root = os.path.dirname(__file__)

            # find the template
            path = os.path.join(root, 'templates', 'confirm.html')

            # generate the content
            content = template.render(path, template_values)

            # display the page
            self.response.out.write(content)

            # self.redirect('/delete?key=%s' % key)

        else:
            self.redirect('/')

class View(webapp.RequestHandler):
    '''
    '''
    def post(self):
        '''
        '''
        # not canceled
        if self.request.get('cancel') == '':
            # db key of the expected password
            key = self.request.get('key')

            # get the key to decrypt the password
            secret = self.request.get('secret')

            # get the encrypted password from the db
            password = model.Password().get(key)

            # get the current visit for the current user
            visit = utils.get_visit()

            # the check is ok, we display the
            decrypted_pwd = utils.decrypt(password.pwd, secret)

            # regex for the pwd check
            re_pwd = re.compile('[^a-zA-Z0-9]')

            if len(re_pwd.findall(decrypted_pwd)) > 0:
                # get the number of attempts
                number_of_attempts = visit.number_of_attempts

                # compute a time to wait
                wait_time = math.pow(number_of_attempts, 3.0)

                # increase the number of attempts
                visit.number_of_attempts += 1

                # title
                title = 'Error'

                # we display the decrypted password
                message = 'Wrong secret key!'

            else:
                # empty the number of attempts
                visit.number_of_attempts = 0

                # no time to wait its ok
                wait_time = 0

                # title
                title = password.login

                # we display the decrypted password
                message = decrypted_pwd

            # save the new status for the user attempts
            visit.put()

            # display the error message
            utils.display_message(self.response, title, message)

            # you failed! wait now for your next turn!
            time.sleep(wait_time)

        # 'Cancel' go back to the list
        else:
            self.redirect('/')


class Edit(webapp.RequestHandler):
    '''
    '''
    def get(self):
        '''
        '''
        # db key of the expected password
        key = self.request.get('key')

        # get the password object
        password = model.Password().get(key)

        # set the template
        template_values = { 'title': 'Edit',
                            'password': password,
                            'key': password.key() }

        # root path
        root = os.path.dirname(__file__)

        # find the template
        path = os.path.join(root, 'templates', 'edit.html')

        # generate the content
        content = template.render(path, template_values)

        # display the page
        self.response.out.write(content)


class Update(webapp.RequestHandler):
    '''
    '''
    def post(self):
        '''
        '''
        # update the password
        if self.request.get('cancel') == '':
            # get the value to compare
            pwd = self.request.get('password').strip()
            confirm = self.request.get('confirm').strip()

            # check the confirm value
            if pwd == confirm:
                # db key of the expected password
                key = self.request.get('key')

                try:
                    # get the password object
                    password = model.Password().get(key)
                except:
                    password = model.Password()

                # create the new password
                if password == None:
                    password = model.Password()

                # set the value
                password.category = self.request.get('category').strip()
                password.login = self.request.get('login').strip()

                # get the key to decrypt the password
                secret = self.request.get('secret')

                if secret != '' and pwd != '':
                    #decrypt the password
                    password.pwd = utils.encrypt(pwd, secret)

                # save
                password.put()

            # pwd not well confirmed
            else:
                # title
                title = 'Error'

                # set the message
                msg = 'Password and confirmation don\'t match!'

                # we have an error message
                return utils.display_message(self.response, title, msg)

        # go back to the list
        self.redirect('/')

class Delete(webapp.RequestHandler):
    '''
    '''
    def post(self):
        '''
        '''
        # update the password
        if self.request.get('ok') != '':
            # db key of the expected password
            key = self.request.get('key')

            # get the password object
            password = model.Password().get(key)

            if password:
                # delete a password from a key value
                password.delete()

        # go back to the list
        self.redirect('/')

class List(webapp.RequestHandler):
    '''
    '''
    def get(self):
        '''
        '''
        # retrieve the data
        passwords = model.Password.all().order('category')

        if passwords.count() == 0:
            passwords = None

        # set the template
        template_values = { 'title': 'Home',
                            'home': True,
                            'passwords': passwords }


        # root path
        root = os.path.dirname(__file__)

        # find the template
        path = os.path.join(root, 'templates', 'list.html')

        # generate the content
        content = template.render(path, template_values)

        # display the page
        self.response.out.write(content)

def main():
    application = webapp.WSGIApplication(
                                        [
                                            ('/', List),
                                            ('/login', Login),
                                            ('/logout', Logout),
                                            ('/check', Check),
                                            ('/edit', Edit),
                                            ('/new', New),
                                            ('/update', Update),
                                            ('/view', View),
                                            ('/delete', Delete),
                                        ],
                                        debug=True)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == "__main__":
    main()
